﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.Xml.Serialization;
using System.IO;

namespace Mimoza.AgentLayer
{
    public class SettingsRegistry
    {
        public const string c_MimozaRegistryKeyName = @"SOFTWARE\Mimoza";
        const string c_AppRegistryKeyName = @"Agent";
        const string c_AppRegistryKeyPath = c_MimozaRegistryKeyName + @"\" + c_AppRegistryKeyName;

        const string c_BroadcastPort = "BroadcastPort";
        const string c_CreateConnectionPeriod = "CreateConnectionPeriod";
        const string c_ServerPort = "ServerPort";
        const string c_HostId = "HostId";
        const string c_FindServerPeriod = "FindServerPeriod";
        const string c_ServerHost = "ServerHost";
        const string c_ServerAddr = "ServerAddr";
        const string c_SyncId = "SyncId";
        const string c_IsTimeSynchronizeFromServer = "IsTimeSynchronizeFromServer";

        public SettingsRegistry()
        {
        }

        public void Load(Settings settings)
        {
            RegistryKey localMachineKey = Registry.LocalMachine;

            RegistryKey appKey = localMachineKey.OpenSubKey(c_AppRegistryKeyPath);

            if (appKey==null)
            {
                Common.Logger.Log.Warn("SettingsRegistry applicaion key is missing.");
            
                return;
            }

            Settings defaultSetting = new Settings();

            settings.BroadcastTransportPort = (int)appKey.GetValue(c_BroadcastPort,
                defaultSetting.BroadcastTransportPort);

            settings.CreateConnectionPeriod = (int)appKey.GetValue(c_CreateConnectionPeriod,
                defaultSetting.CreateConnectionPeriod);

            settings.ServerTransportPort = (int)appKey.GetValue(c_ServerPort,
                defaultSetting.ServerTransportPort);

            settings.FindServerPeriod = (int)appKey.GetValue(c_FindServerPeriod,
                defaultSetting.FindServerPeriod);

            settings.HostId = appKey.GetValue(c_HostId,
                defaultSetting.HostId) as string;

            settings.ServerHost = appKey.GetValue(c_ServerHost,
                defaultSetting.ServerHost) as string;

            settings.ServerAddr = appKey.GetValue(c_ServerAddr,
                defaultSetting.ServerAddr) as string;

            string strGuid = appKey.GetValue(c_SyncId,"") as string;
            if (strGuid != "")
            {
                settings.PolicySynchronizationId = new Guid(strGuid);
            }

            settings.IsTimeSynchronizeFromServer = false;
            string flagStr = appKey.GetValue(c_IsTimeSynchronizeFromServer, "") as string;
            if (flagStr != "")
            {
                bool res = false;
                res = bool.Parse(flagStr);
                settings.IsTimeSynchronizeFromServer = res;
            }

            if (string.IsNullOrEmpty(settings.HostId))
            {
                LoadFromFile(settings); 
            }

            PrintSettings("SettingsRegistry.Load :", settings);
        }

        public void Save(Settings settings)
        {
            RegistryKey localMachineKey = Registry.LocalMachine;

            RegistryKey appKey = localMachineKey.OpenSubKey(c_AppRegistryKeyPath,true);

            if (appKey == null)
            {
                Common.Logger.Log.Warn("SettingsRegistry.Save applicaion key is missing.");

#if WindowsCE
                appKey = localMachineKey.CreateSubKey(c_AppRegistryKeyPath);
#else
                appKey = localMachineKey.CreateSubKey(c_AppRegistryKeyPath,
                    RegistryKeyPermissionCheck.ReadWriteSubTree);
#endif

                if (appKey == null)
                {
                    Common.Logger.Log.Warn("SettingsRegistry.Save can't create applicaion key.");

                    return;
                }
            }

            appKey.SetValue(c_BroadcastPort, settings.BroadcastTransportPort, RegistryValueKind.DWord);

            appKey.SetValue(c_CreateConnectionPeriod, settings.CreateConnectionPeriod, RegistryValueKind.DWord);

            appKey.SetValue(c_ServerPort, settings.ServerTransportPort, RegistryValueKind.DWord);

            appKey.SetValue(c_FindServerPeriod, settings.FindServerPeriod, RegistryValueKind.DWord);

            appKey.SetValue(c_HostId, settings.HostId, RegistryValueKind.String);

            appKey.SetValue(c_ServerHost, settings.ServerHost, RegistryValueKind.String);

            appKey.SetValue(c_ServerAddr, settings.ServerAddr, RegistryValueKind.String);

            appKey.SetValue(c_SyncId, settings.PolicySynchronizationId.ToString(), RegistryValueKind.String);

            appKey.SetValue(c_IsTimeSynchronizeFromServer, settings.IsTimeSynchronizeFromServer.ToString(), RegistryValueKind.String);

            SaveToFile(settings);

            PrintSettings("SettingsRegistry.Save :", settings);
        }

        void SaveToFile(Settings settings)
        {
            Common.Logger.Log.Info("SettingsRegestry.SaveToFile:");

            XmlSerializer serializer = new XmlSerializer(typeof(Settings));
            using(FileStream fs = File.Open(GetSettingsFilePathName(), FileMode.Create))
            {
                serializer.Serialize(fs, settings);
            }
        }

        void LoadFromFile(Settings settings)
        {
            Common.Logger.Log.Info("SettingsRegestry.LoadFromFile:");

            XmlSerializer deserializer = new XmlSerializer(typeof(Settings));
            try
            {
                using (FileStream fs = File.Open(GetSettingsFilePathName(), FileMode.Open))
                {
                    settings = deserializer.Deserialize(fs) as Settings;
                    settings.PolicySynchronizationId = Guid.Empty; // policy sync id stored in regestry only (regestry rewrite on upgrade and terminal totally synced with service)
                }
            }
            catch (Exception e)
            {
                Common.Logger.Log.Warn("SettingsRegestry.LoadFromFile: error - '" + e.ToString() + "'");
            }
        }

        string GetSettingsFilePathName()
        {
            const string SettingsFileName = "settings.dat";

            return Path.Combine(Common.GlobalSettings.DataPath, SettingsFileName);
        }

        void PrintSettings(string caption, Settings settings)
        {
            Common.Logger.Log.Info(caption + 
                "\n\tBroadcastTransportPort - " + settings.BroadcastTransportPort.ToString() + 
                "\n\tServerTransportPort - " + settings.ServerTransportPort.ToString() + 
                "\n\tFindServerPeriod - " + settings.FindServerPeriod.ToString() + 
                "\n\tServerAddr - " + settings.ServerAddr.ToString() + 
                "\n\tPolicySynchronizationId - " + settings.PolicySynchronizationId.ToString() + 
                "\n\tIsTimeSynchronizeFromServer - " + settings.IsTimeSynchronizeFromServer.ToString() +
                "."
            );
        }
    }
}
